import os
import csv
import secrets
import string
from flask import Flask, render_template, request, redirect, url_for, flash, send_file, jsonify
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
from flask_bootstrap import Bootstrap
from werkzeug.utils import secure_filename

app = Flask(__name__)
app.config['SECRET_KEY'] = 'your-secret-key-change-this'
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['MAX_CONTENT_LENGTH'] = 50 * 1024 * 1024  # 16MB max file size

# 初始化扩展
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
login_manager.login_message = '请先登录'
bootstrap = Bootstrap(app)

# 学生数据CSV文件路径
CSV_FILE = '计科1班-软件开发综合实践2025-学号-姓名.csv'

# 实验名称列表
EXPERIMENTS = ['期末大作业']

# 创建上传目录
for exp in EXPERIMENTS:
    os.makedirs(os.path.join(app.config['UPLOAD_FOLDER'], exp), exist_ok=True)

class User(UserMixin):
    def __init__(self, student_id, name, password=None):
        self.id = student_id
        self.student_id = student_id
        self.name = name
        self.password = password

@login_manager.user_loader
def load_user(user_id):
    users = load_users_from_csv()
    for user in users:
        if user.id == user_id:
            return user
    return None

def load_users_from_csv():
    """从CSV文件加载用户数据"""
    users = []
    try:
        with open(CSV_FILE, 'r', encoding='utf-8') as file:
            reader = csv.reader(file)
            next(reader)  # 跳过标题行
            for row in reader:
                if len(row) >= 2:
                    student_id = row[0].strip()
                    name = row[1].strip()
                    password = row[2].strip() if len(row) >= 3 else None
                    users.append(User(student_id, name, password))
    except Exception as e:
        print(f"读取CSV文件时出错: {e}")
    return users

def generate_password():
    """生成16位强密码"""
    characters = string.ascii_letters + string.digits
    return ''.join(secrets.choice(characters) for _ in range(16))

def update_user_password(student_id, password):
    """更新用户密码"""
    try:
        # 读取所有数据
        rows = []
        with open(CSV_FILE, 'r', encoding='utf-8') as file:
            reader = csv.reader(file)
            rows = list(reader)
        
        # 更新对应学生的密码
        for i, row in enumerate(rows):
            if i > 0 and len(row) >= 2 and row[0].strip() == student_id:
                if len(row) < 3:
                    row.extend([''] * (3 - len(row)))
                row[2] = password
                break
        
        # 写回文件
        with open(CSV_FILE, 'w', encoding='utf-8', newline='') as file:
            writer = csv.writer(file)
            writer.writerows(rows)
        return True
    except Exception as e:
        print(f"更新CSV文件时出错: {e}")
        return False

def authenticate_user_first_time(student_id, name):
    """首次登录验证（学号+姓名）"""
    users = load_users_from_csv()
    for user in users:
        if user.student_id == student_id and user.name == name and not user.password:
            return user
    return None

def authenticate_user_with_password(student_id, password):
    """密码登录验证（学号+密码）"""
    users = load_users_from_csv()
    for user in users:
        if user.student_id == student_id and user.password == password:
            return user
    return None

def check_user_has_password(student_id):
    """检查用户是否已设置密码"""
    users = load_users_from_csv()
    for user in users:
        if user.student_id == student_id:
            return bool(user.password)
    return False

def allowed_file(filename):
    """检查文件是否为PDF格式"""
    return '.' in filename and filename.rsplit('.', 1)[1].lower() == 'pdf'

def get_assignment_status(student_id, name):
    """获取学生作业提交状态"""
    status = {}
    for exp in EXPERIMENTS:
        filename = f"{exp}-{student_id}-{name}.pdf"
        filepath = os.path.join(app.config['UPLOAD_FOLDER'], exp, filename)
        status[exp] = os.path.exists(filepath)
    return status

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        student_id = request.form.get('student_id', '').strip()
        
        if not student_id:
            flash('请输入学号', 'error')
            return render_template('login.html')
        
        # 检查用户是否已设置密码
        has_password = check_user_has_password(student_id)
        
        if has_password:
            # 密码登录
            password = request.form.get('password', '').strip()
            if not password:
                flash('请输入密码', 'error')
                return render_template('login.html', login_mode='password', student_id=student_id)
            
            user = authenticate_user_with_password(student_id, password)
            if user:
                login_user(user)
                return redirect(url_for('assignments'))
            else:
                flash('学号或密码不正确', 'error')
                return render_template('login.html', login_mode='password', student_id=student_id)
        else:
            # 首次登录
            name = request.form.get('name', '').strip()
            if not name:
                flash('请输入姓名', 'error')
                return render_template('login.html', login_mode='first_time', student_id=student_id)
            
            user = authenticate_user_first_time(student_id, name)
            if user:
                # 生成密码并更新
                new_password = generate_password()
                if update_user_password(student_id, new_password):
                    user.password = new_password
                    login_user(user)
                    flash(f'欢迎首次登录！您的登录密码是：{new_password}，请务必记住！', 'success')
                    return render_template('password_generated.html', password=new_password, student_id=student_id, name=name)
                else:
                    flash('系统错误，请重试', 'error')
            else:
                flash('学号或姓名不正确，请检查后重试', 'error')
                return render_template('login.html', login_mode='first_time', student_id=student_id)
    
    # GET请求，检查是否有学号参数
    student_id = request.args.get('student_id', '')
    if student_id and check_user_has_password(student_id):
        return render_template('login.html', login_mode='password', student_id=student_id)
    
    return render_template('login.html')

@app.route('/assignments')
@login_required
def assignments():
    assignment_status = get_assignment_status(current_user.student_id, current_user.name)
    return render_template('assignments.html', 
                         experiments=EXPERIMENTS, 
                         assignment_status=assignment_status)

@app.route('/upload/<experiment>', methods=['POST'])
@login_required
def upload_assignment(experiment):
    if experiment not in EXPERIMENTS:
        return jsonify({'success': False, 'message': '无效的实验名称'})
    
    if 'file' not in request.files:
        return jsonify({'success': False, 'message': '没有选择文件'})
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({'success': False, 'message': '没有选择文件'})
    
    if not allowed_file(file.filename):
        return jsonify({'success': False, 'message': '只能上传PDF格式的文件'})
    
    # 生成新文件名
    filename = f"{experiment}-{current_user.student_id}-{current_user.name}.pdf"
    filepath = os.path.join(app.config['UPLOAD_FOLDER'], experiment, filename)
    
    try:
        # 确保目录存在
        os.makedirs(os.path.dirname(filepath), exist_ok=True)
        file.save(filepath)
        return jsonify({'success': True, 'message': f'{experiment}作业上传成功'})
    except Exception as e:
        return jsonify({'success': False, 'message': f'上传失败: {str(e)}'})

@app.route('/delete/<experiment>', methods=['POST'])
@login_required
def delete_assignment(experiment):
    if experiment not in EXPERIMENTS:
        return jsonify({'success': False, 'message': '无效的实验名称'})
    
    filename = f"{experiment}-{current_user.student_id}-{current_user.name}.pdf"
    filepath = os.path.join(app.config['UPLOAD_FOLDER'], experiment, filename)
    
    try:
        if os.path.exists(filepath):
            os.remove(filepath)
            return jsonify({'success': True, 'message': f'{experiment}作业删除成功'})
        else:
            return jsonify({'success': False, 'message': '文件不存在'})
    except Exception as e:
        return jsonify({'success': False, 'message': f'删除失败: {str(e)}'})

@app.route('/preview/<experiment>')
@login_required
def preview_assignment(experiment):
    if experiment not in EXPERIMENTS:
        flash('无效的实验名称', 'error')
        return redirect(url_for('assignments'))
    
    filename = f"{experiment}-{current_user.student_id}-{current_user.name}.pdf"
    filepath = os.path.join(app.config['UPLOAD_FOLDER'], experiment, filename)
    
    if not os.path.exists(filepath):
        flash(f'{experiment}作业文件不存在', 'error')
        return redirect(url_for('assignments'))
    
    return send_file(filepath, as_attachment=False)



@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash('已退出登录', 'info')
    return redirect(url_for('login'))

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=25613, debug=True) 